// INSE6260-ATM Simulator Project

/**
 * controller package interfaces view and model.
 */
package com.inse6260.atms.controller;

import com.inse6260.atms.model.*;
import com.inse6260.atms.view.*;

import java.util.ArrayList;
import java.util.Hashtable;

/**
 *
 * @author dimitri.tiago
 */
public class ATMSController
{
    // fields
    private Atms    myAtms;
    private Screen  myScreen;
    private String  currTransaction;

    private Hashtable<String,String> currTransParams;

    /**
     * Default constructor initializes controller
     */
    public ATMSController()
    {
        myAtms          = new Atms();
        myScreen        = new Screen(this);
        currTransaction = "";
        currTransParams = new Hashtable<String, String>();
    }

    /**
     * Inputs card number into ATMS
     * @param cardNumber bank client card number
     * @return string with validation result
     */
    public String inputCardNumber(String inputCardNumber)
    {
        // local variables
        String inputCardResult = "";
        int cardNumber = Integer.parseInt(inputCardNumber);

        // process card number
        inputCardResult = myAtms.validateCardNumber(cardNumber);

        return  inputCardResult;
    }

    /**
     * Inputs password into ATMS
     * @param inputPassword bank client input password
     * @return string with validation result
     */
    public String inputPassword(String inputPassword)
    {
        // local variables
        String authorizationValidation = "";
        boolean authorized = false;
        int pin = Integer.parseInt(inputPassword);

        // process card number
        authorized = myAtms.authorize(pin);

        if (authorized == true)
        {
            authorizationValidation = String.format("%s", "Success");
        }
        else
        {
            authorizationValidation = myAtms.getAuthFailureReason();
        }

        return  authorizationValidation;
    }

    /**
     * Asks Screen to show option panel
     */
    public void showATMSMainMenu()
    {
        // clear current transaction state
        currTransaction = "";
        currTransParams.clear();

        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        myScreen.setATMSMainManuPanel();
    }

    /**
     * Asks Screen to show withdrawal menu
     */
    public void showWithdrawalMenu()
    {
        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        myScreen.setWithdrawalPanel();
    }

     /**
     * Asks Screen to show withdrawal menu
     */
    public void showAccSelPanel()
    {
        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        if (getAccList() == null)
        {
            showAnotherTransPanel("No accounts related to card number.");
        }
        else
        {
            myScreen.setAccSelPanel();
        }
    }

    /**
    * Asks Screen to show target account selection panel
    */
    public void showTgtAccSelPanel()
    {
        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        if (getAccList() == null)
        {
            showAnotherTransPanel("No accounts related to card number.");
        }
        else if (getAccList().length == 1)
        {
            showAnotherTransPanel("No accounts related to card number.");
        }
        else
        {
            myScreen.setTgtAccSelPanel();
        }
    }

    public void showNextPanel()
    {
        // determine next panel for screen based on transaction
        if (currTransaction.equalsIgnoreCase("withdrawal"))
        {
            if (currTransParams.containsKey("account"))
            {
                showWithdrawalMenu();
            }

            if (currTransParams.containsKey("otherAccount"))
            {
                // TODO
            }
        }

        if (currTransaction.equalsIgnoreCase("deposit"))
        {
            if (currTransParams.containsKey("account"))
            {
                // request envelope
                myScreen.showEnvelopeSlot();
            }

            if (currTransParams.containsKey("amount"))
            {
                showAccSelPanel();
            }
        }

        if (currTransaction.equalsIgnoreCase("transfer"))
        {
            if (currTransParams.containsKey("account"))
            {
                showTgtAccSelPanel();
            }
            else if (currTransParams.containsKey("amount"))
            {
                showAccSelPanel();
            }
        }

        if (currTransaction.equalsIgnoreCase("information"))
        {
            showAccInfoPanel();
        }
    }

    public void showAnotherTransPanel(String header)
    {
        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        myScreen.setAnotherTransPanel(header);
    }

    public void showLogInPanel()
    {
        // clear current transaction state
        currTransaction = "";
        currTransParams.clear();

        // cler atms state
        myAtms.resetAtm();

        // dispaly log in panel
        myScreen.showCurrentScreenPanel(false);
        myScreen.setLogInPanel();
    }

    public void showAmtInputPanel()
    {
        // hide current screen set option panel
        myScreen.showCurrentScreenPanel(false);
        myScreen.setAmtInputPanel();
    }

    public void showAccInfoMenuPanel()
    {
        myScreen.showCurrentScreenPanel(false);
        myScreen.setAccInfoMenuPanel();
    }

    public void showAccInfoPanel()
    {
        myScreen.showCurrentScreenPanel(false);
        if (getAccList() == null)
        {
            showAnotherTransPanel("No accounts related to card number.");
        }
        else
        {
            myScreen.setAccInfoPanel();
        }
    }

    public boolean isCurrScreenVisible()
    {
        return myScreen.isCurrScreenVisible();
    }

    /**
     * Requests withdrawal of amount
     * @param withdrawAmount amount to withdraw
     */
    public void requestWithdrawal(String withdrawAmount)
    {
        String transResult = "";

        currTransParams.put("amount", withdrawAmount);
        transResult = myAtms.executeTransaction("withdrawal", currTransParams);
        if (transResult.equalsIgnoreCase("success"))
        {
            myScreen.showDispenseCash(withdrawAmount);
        }


        String receipt = myAtms.getReciept();
        myScreen.showReceipt(receipt);

        // prompt user for another transaction
        showAnotherTransPanel(transResult);
    }

    public void requestDeposit()
    {
        String transResult = "";

        transResult = myAtms.executeTransaction("deposit", currTransParams);
        String receipt = myAtms.getReciept();
        myScreen.showReceipt(receipt);

        // prompt user for another transaction
        showAnotherTransPanel(transResult);
    }

    public void requestTransfer()
    {
        String transResult = "";

        transResult = myAtms.executeTransaction("transfer", currTransParams);
        String receipt = myAtms.getReciept();
        myScreen.showReceipt(receipt);

        // prompt user for another transaction
        showAnotherTransPanel(transResult);
    }

    public String requestAccInfo()
    {
        String accInfo = "";

        // get and prepare account balance
        if (currTransParams.containsKey("balance"))
        {
            // get accounts information
            String[] atmsAccInfo = myAtms.getAccInformation();
            String   accRecord   = "";

            // TODO: handle case where no accounts exist.
                
            // obtain requested account record
            for (String record : atmsAccInfo)
            {
               String[] recItem = record.split("-");

               // compare account numbers
               String reqAcc = currTransParams.get("account");
               if (recItem[1].equalsIgnoreCase(reqAcc))
               {
                   // found requested account record
                   accRecord = record;
               }
            }

            // construct information
            String[] accDetails = accRecord.split("-");
            accInfo = String.format("%s\n%s\n%s%s\n%s%s\n%s%s","ACCOUNT BALANCE:","------------------------------",
                   "Account Type: ", accDetails[0], "Account #: ", accDetails[1], "Balance: $", accDetails[2]);
        }

        // get and prepare account list
        if (currTransParams.containsKey("accList"))
        {
            // get accounts information
            StringBuffer strBuffer = new StringBuffer();
            String[] accounts = myAtms.getAccInformation();
            String tmpString = "";

            // TODO: handle case where no accounts exist.

            // build accounts list string
            tmpString = String.format("%-20s%-20s%-20s\n", "Account Type", "Account #", "Account Balance");
            strBuffer.append(tmpString);
            for (String record : accounts)
            {
                String[] accRecord = record.split("-");
                tmpString = String.format("%-20s%-20s%-20s\n", accRecord[0], accRecord[1], accRecord[2]);
                strBuffer.append(tmpString);
            }

            accInfo = strBuffer.toString();
        }

        // get and prepare account statement
        if (currTransParams.containsKey("statement"))
        {
            int accountNumber = Integer.parseInt(currTransParams.get("account"));
            return myAtms.getAccStatement(accountNumber);
        }

        return accInfo;
    }

    public String[] getAccList()
    {
        // local variables
        String[] acctsInfo = myAtms.getAccInformation();
        if (acctsInfo == null)
        {
            return null;
        }

        String[] accList   = new String[acctsInfo.length];

        // prepare account list
        for (int i = 0; i < accList.length ; i++)
        {
             String[] accListItem = acctsInfo[i].split("-");
             accList[i] = accListItem[0] + "-" + accListItem[1];
        }

        return accList;
    }

    public String[] getTgtAccList()
    {
        // local variables
        String[] acctsInfo             = myAtms.getAccInformation();
        if (acctsInfo == null)
        {
            return null;
        }
        
        ArrayList<String> accArrayList = new ArrayList<String>();

        // prepare account list
        for (int i = 0; i < acctsInfo.length ; i++)
        {
             String[] accListItem = acctsInfo[i].split("-");

             if (!accListItem[1].equalsIgnoreCase(currTransParams.get("account")))
             {
                accArrayList.add(accListItem[0] + "-" + accListItem[1]);
             }
        }

        return accArrayList.toArray(new String[0]);
    }

    // added to support withdrawal other input
    public String getCurrTransaction()
    {
        return currTransaction;
    }

    public void setCurrTransaction(String currTransaction)
    {
        this.currTransaction = currTransaction;
    }

    public void setCurrTransParams(String paramName, String paramValue)
    {
        currTransParams.put(paramName, paramValue);
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                ATMSController myAtm = new ATMSController();
            }
        });
    }
}